package com.osce.ex.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csce.domain.entity.exam.ExExam;
import com.csce.domain.entity.exam.ExExamRecord;
import com.csce.domain.entity.exam.vo.AllotExRecord;
import com.csce.domain.entity.exam.vo.ExExamQuestion;
import com.csce.domain.entity.exam.vo.ExStatus;
import com.csce.domain.entity.exam.vo.RecordExcelVo;
import com.doudou.core.container.ListUtil;
import com.doudou.core.container.SetUtil;
import com.doudou.core.lang.ObjUtil;
import com.doudou.core.date.DateUtil;
import com.osce.common.utils.DateUtils;
import com.osce.ex.mapper.ExExamMapper;
import com.osce.ex.mapper.ExExamRecordMapper;
import com.osce.ex.service.tools.ExService;
import com.osce.interfaces.ex.IExExamRecordService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 考试记录Service业务层处理
 *
 * @author zzx
 * @since 2023-08-10
 */
@Service
public class ExExamRecordServiceImpl extends ServiceImpl<ExExamRecordMapper, ExExamRecord> implements IExExamRecordService {
    private static final Log log = LogFactory.get(IExExamRecordService.class);

    @Resource
    private ExExamMapper exExamMapper;
    @Resource
    private ExService exService;

    /**
     * 查询考试记录
     *
     * @param id 考试记录主键
     * @return 考试记录
     */
    @Override
    public ExExamRecord selectExExamRecordById(Long id) {
        ExExamRecord record = checkRecord(baseMapper.selectExExamRecordById(id), true);
        ExExam exam = record.getExam();
        List<Long> questionIds = exExamMapper.selectExQuestionIdsById(record.getExamId());//查询考试下的题目id集合
        //如果完成状态，返回已做完题目详情
        if (record.getStatus().equals(3)) {
            Map<Long, ExExamQuestion> recordQuestions = baseMapper.selectRecordQuestions(id);
            exam.setQuestionIds(questionIds);
            return record.setExamQuestions(recordQuestions);
        }
        //如果不是固定组卷并且题库未完成，则需要把打乱题目顺序
        if (exam.getFixed() != 1 && record.getStatus() != 3 && record.getStatus() != 4) {
            exam.setQuestionIds(exService.disruptOrder(questionIds));
        } else {
            exam.setQuestionIds(questionIds);
        }
        return record;
    }


    /**
     * 查询考试记录列表
     *
     * @param exExamRecord 考试记录
     * @return 考试记录
     */
    @Override
    public List<ExExamRecord> selectExExamRecordList(ExExamRecord exExamRecord) {
        return baseMapper.selectExExamRecordList(exExamRecord);
    }

    /**
     * 检查考试记录列表
     *
     * @param exExamRecords 考试记录
     * @return 考试记录
     */
    @Override
    public List<ExExamRecord> checkExExamRecordList(List<ExExamRecord> exExamRecords) {
        return exExamRecords.stream().map(e -> checkRecord(e, false)).collect(Collectors.toList());
    }


    @Override
    public List<RecordExcelVo> selectExExamRecordExcelList(ExExamRecord exExamRecord) {
        List<ExExamRecord> exExamRecords = selectExExamRecordList(exExamRecord);
        List<RecordExcelVo> list = ListUtil.list(true);
        for (ExExamRecord record : exExamRecords) {
            list.add(RecordExcelVo.builder().
                    nickName(record.getNickName()).
                    examName(record.getExam().getName()).
                    appointDate(record.getAppointDate()).
                    rightCount(record.getRightCount()).
                    score(record.getScore()).
                    startTime(record.getStartTime()).
                    endTime(record.getEndTime()).
                    answerTime(DateUtil.secondFormat(record.getAnswerTime())).
                    build());
        }
        return list;
    }

    /**
     * 新增考试记录
     *
     * @param exExamRecord 考试记录
     * @return 结果
     */
    @Override
    public int insertExExamRecord(ExExamRecord exExamRecord) {
        exExamRecord.setCreateTime(DateUtils.getNowDate());
        return baseMapper.insertExExamRecord(exExamRecord);
    }

    /**
     * 修改考试记录
     *
     * @param exExamRecord 考试记录
     * @return 结果
     */
    @Override
    public int updateExExamRecord(ExExamRecord exExamRecord) {
        return baseMapper.updateExExamRecord(exExamRecord);
    }

    /**
     * 批量删除考试记录
     *
     * @param ids 需要删除的考试记录主键
     * @return 结果
     */
    @Override
    public int deleteExExamRecordByIds(Long[] ids) {
        return baseMapper.deleteExExamRecordByIds(ids);
    }

    /**
     * 删除考试记录信息
     *
     * @param id 考试记录主键
     * @return 结果
     */
    @Override
    public int deleteExExamRecordById(Long id) {
        return baseMapper.deleteExExamRecordById(id);
    }

    /**
     * 获取当前已预约的考试编号数组
     *
     * @return [exam_id]
     */
    @Override
    public List<Long> selectAppointExamIds(Long userId) {
        return SetUtil.toList(baseMapper.selectAppointExamIds(userId));
    }

    @Override
    @Transactional
    public int submit(Long id, Integer timer, Map<Long, Object> answers) {
        //查询考试详情
        ExExamRecord record = baseMapper.selectExExamRecordById(id);
        ExStatus judge = exService.judge(id, exExamMapper.selectExQuestionIdsById(record.getExamId()), answers);
        record = ExExamRecord.builder().id(id).status(3).
                rightCount(judge.getSuccess()).score(judge.getScore()).
                endTime(new Date()).answerTime(timer).build();
        //批量添加做题详情
        insertExRecordQuestion(judge.getExamQuestionList());
        return updateExExamRecord(record);
    }

    @Override
    public List<Long> selectUserIdsByExam(Long examId) {
        return baseMapper.selectUserIdsByExam(examId);
    }

    /**
     * 批量分配学生
     *
     * @param allot
     * @return
     */
    @Override
    public int allotUsers(AllotExRecord allot) {
        List<ExExamRecord> exExamRecords = allot.getUserIds().stream().map(userId -> ExExamRecord.builder().
                examId(allot.getExamId()).
                userId(userId).
                appointDate(allot.getAllotDate()).status(1).build()).collect(Collectors.toList());
        return baseMapper.batchExExamRecord(exExamRecords);
    }

    /**
     * 添加做题详情
     */
    private int insertExRecordQuestion(List<ExExamQuestion> examQuestionList) {
        return baseMapper.insertExRecordQuestion(examQuestionList);
    }


    /**
     * 检查记录
     * 1、isStart=true 如果开始时间为空，则设置开始时间为当前时间，并设置状态为2（已开始）
     * 2、如果开始时间不为空，但是结束时间为空或者状态不为3和4（已完成、未完成）
     * 则判断开始时间加上考试规定时间是否在当前时间之内
     * 如果时间已经超出，修改状态为4（未完成）、对题数和得分都为0
     */
    private ExExamRecord checkRecord(ExExamRecord record, boolean isStart) {
        try {
            if (isStart && ObjUtil.isEmpty(record.getStartTime())) {
                record.setStatus(2);
                record.setStartTime(new Date());
                baseMapper.updateExExamRecord(record);
            }
            if (record.getStatus() != 1 && record.getStatus() != 2) {
                return record;
            }
            //判断时间  用户开始考试时间加上考试限制时间
            DateTime clippingTime = DateTime.of(record.getStartTime()).offset(DateField.SECOND, record.getExam().getDuration());
            //如果当前时间在考试限制时间之后
            if (DateTime.now().after(clippingTime)) {
                record.setStatus(4);
                record.setScore(0D);
                record.setRightCount(0);
                record.setAnswerTime(0);
                baseMapper.updateExExamRecord(record);
            }
        } catch (Exception e) {
            log.error("检查考试记录异常", e);
        }
        return record;
    }
}
